package pers.duorhs.easierfeign.invoker;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import pers.duorhs.easierfeign.exception.RemoteInvokeException;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Duorhs
 * @date 2022/1/10 14:35
 */
@Slf4j
public class EasierFeignServiceInvoker {

    @Autowired
    @Qualifier("EasierFeignServiceMap")
    private ConcurrentHashMap<String, Object> serviceMap;

    @Autowired
    @Qualifier("EasierFeignMethodMap")
    private ConcurrentHashMap<String, Method> methodMap;

    public String getResultAsJsonString(String serviceName, String methodName, String args) throws InvocationTargetException, IllegalAccessException {
        Object service = serviceMap.get(serviceName);
        if (service == null) {
            log.error("{}", "A remote client called " + serviceName + ",but failed.");
            return JSON.toJSONString(new RemoteInvokeException("ERROR: Cannot find the class pointed to " + serviceName + ", please check the parameter."));
        }
        Method method = methodMap.get(serviceName + "#" + methodName);
        if (method == null) {
            log.error("{}", "A remote client tried to invoke method" + serviceName + "#" + methodName + ",but failed.");
            return JSON.toJSONString(new RemoteInvokeException("ERROR: Unable to invoke the method pointed to " + serviceName + "#" + methodName + ", please check the parameter or modifier."));
        }

        Class<?>[] parameterTypes = method.getParameterTypes();

        JSONArray argsArray = JSON.parseArray(args);

        List<Object> argsList = new ArrayList<>();

        //把参数列表对应起来
        if (args != null) {
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> type = parameterTypes[i];

                // DONE 数组参数的处理
                if (type.isArray()) {
                    JSONArray jsonArray = (JSONArray) argsArray.get(i);
                    int size = jsonArray.size();
                    Object array = Array.newInstance(type.getComponentType(), size);
                    for (int j = 0; j < size; j++) {
                        Array.set(array, j, jsonArray.get(j));
                    }
                    argsList.add(array);
                } else {
                    String argStr = JSON.toJSONString(argsArray.get(i));
                    argsList.add(JSON.parseObject(argStr, type));
                }
            }
        }
        return JSON.toJSONString(method.invoke(service, argsList.toArray()));
    }
}
